import {
  BaseCommand,
  CommandDialog,
  ICurve,
  MessageTip,
  ParameterObjectType,
} from '@amcax/base';
import { ctx2 } from '@app-cad/module';

import i18n from '@app-cad/common/utils/i18next';
import { useEffect, useRef, useState } from 'react';
import { PickInputForFocus2D } from '@app-cad/common/components/command-form/auto-focus/pick-input';
import {
  CommandDialogProps,
  CommandFormWrapper,
} from '@app-cad/common/components/command-form';
import { SketchTransformTool } from '@app-base/common/utils/renderObjects.ts/SketchTransformTool';
import { useCommand } from '@app-base/common/hooks/useCommand';
import { CommandFormFooter } from '@app-base/common/components/command-form/footer';
import { wsApi } from '@app-base/server';
import { sketchEventCenter } from '@app-base/environments/nextcad/events/SketchEventCenter';
import { isEqual } from 'lodash';
import { ReturnDataInfo } from '../../CmdBase';
import { renderSketch, resetRenderDim } from '@app-base/common/utils';
import { Checkbox } from 'antd';
import { InputWithFormat } from '@app-base/common/components/command-form/InputWithFormat';

function CmdTransform({ onClose, title }: CommandDialogProps) {
  const [transformObjects, setTransformObjects] = useState<string[]>([]);
  const [makeCopy, setMakeCopy] = useState(false);
  const [keepConstraint, setKeepConstraint] = useState(false);
  const [ratio, setRatio] = useState(1);
  const sketchTransformToolRef = useRef<SketchTransformTool>();
  const [allowMarqueeSelect, setAllowMarqueeSelect] = useState(true);

  useEffect(() => {
    selectObjectsByIds();
    return () => {
      sketchTransformToolRef.current?.destory();
      sketchTransformToolRef.current = null;
    };
    // 选取id实际变化时才触发
  }, [[...transformObjects].sort().join(',')]);

  useCommand('sketch-transform');

  const selectObjectsByIds = () => {
    if (transformObjects.length > 0) {
      sketchTransformToolRef.current?.destory();
      sketchTransformToolRef.current = null;
      const objects = ctx2.cadScene.sketchGroup.children.filter((v) =>
        transformObjects.includes((v.userData?.info as ICurve)?.id),
      );

      sketchTransformToolRef.current = new SketchTransformTool(
        objects,
        setRatio,
        setAllowMarqueeSelect,
      );
      if (ratio !== 1) {
        sketchTransformToolRef.current.applyScale(ratio);
      }
      ctx2.cadScene.assisGroup.add(sketchTransformToolRef.current);

      ctx2.requestRender();
    }
  };

  useEffect(() => {
    sketchTransformToolRef.current?.applyScale(ratio);
  }, [ratio]);

  return (
    <CommandDialog
      title={title}
      placement='topLeft'
      className='sketchDialog'
      onClose={onClose}
    >
      <CommandFormWrapper>
        <PickInputForFocus2D
          value={transformObjects}
          onPick={(val) => setTransformObjects(val)}
          controlled
          isMulti
          placeholder='请选择实体'
          autoFocus
          allowMarqueeSelect={allowMarqueeSelect}
        />
        <Checkbox
          checked={keepConstraint}
          onChange={(e) => {
            const checked = e.target.checked;
            if (!makeCopy && checked) {
              MessageTip.warning('不制作副本时不可保留约束');
              return;
            }
            setKeepConstraint(checked);
          }}
        >
          保留约束
        </Checkbox>
        <Checkbox
          checked={makeCopy}
          onChange={(e) => {
            const checked = e.target.checked;
            if (keepConstraint && !checked) {
              MessageTip.warning('不制作副本时不可保留约束');
              return;
            }
            setMakeCopy(checked);
          }}
        >
          制作副本
        </Checkbox>
        <div className='text-sm'>缩放比例</div>
        <InputWithFormat
          value={ratio}
          inputType={ParameterObjectType.Real}
          onChange={(v) => {
            setRatio(v as number);
            sketchTransformToolRef.current?.applyScale(v as number);
          }}
        />
      </CommandFormWrapper>
      <CommandFormFooter
        onSubmit={async () => {
          const currentSketchId = sketchEventCenter().getSketchInfo().sketchId;
          await wsApi.startTransaction({ n: 'SktTransform' });

          const center = [
            sketchTransformToolRef.current.center.x,
            sketchTransformToolRef.current.center.y,
          ];

          if (sketchTransformToolRef.current.selfRotate !== 0) {
            await wsApi.executeTransaction({
              o: currentSketchId,
              a: {
                curves: transformObjects,
                action: 'rotate',
                center,
                angle:
                  (sketchTransformToolRef.current.selfRotate / Math.PI) * 180,
                makeCopy,
                keepConstraint,
              },
            });
          }

          if (sketchTransformToolRef.current.selfScale !== 1) {
            await wsApi.executeTransaction({
              o: currentSketchId,
              a: {
                curves: transformObjects,
                action: 'scale',
                center,
                factor: sketchTransformToolRef.current.selfScale,
                makeCopy,
                keepConstraint,
              },
            });
          }

          const translateVector = [
            sketchTransformToolRef.current.selfTranslate.x,
            sketchTransformToolRef.current.selfTranslate.y,
          ];

          if (!isEqual(translateVector, [0, 0])) {
            await wsApi.executeTransaction({
              o: currentSketchId,
              a: {
                curves: transformObjects,
                action: 'move',
                vector: translateVector,
                makeCopy,
                keepConstraint,
              },
            });
          }

          const result: ReturnDataInfo = await wsApi.endTransaction();

          await renderSketch(currentSketchId, result);
          resetRenderDim(currentSketchId);
          onClose();
        }}
        onClose={onClose}
      />
    </CommandDialog>
  );
}

export const cmdSketchTransform: BaseCommand = {
  id: 'CmdTransform',
  label: 'command.sketch-cmds.transform',
  icon: 'commands/sketch/transform',
  group: 'sketch',
  create: (label: string, onClose: () => void) => (
    <CmdTransform
      title={i18n.t(label)}
      onClose={onClose}
      placement='topLeft'
    />
  ),
};
